{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**问题：**\n",
    "假设你正在为一个电影推荐系统设计一个简单的KNN算法。我们有以下一些用户的电影评分数据，数据由两个特征组成：用户对电影A和电影B的评分，分别在1-5之间。用户的标签（电影类型偏好）是动作片（标签0）或者是喜剧片（标签1）。我们有一个新用户，他给电影A评分为3，电影B评分为4。请问这个用户可能偏好哪种类型的电影？\n",
    "\n",
    "**数据：**\n",
    "\n",
    "| 用户   | 电影A评分 | 电影B评分 | 偏好类型 |\n",
    "| ------ | --------- | --------- | -------- |\n",
    "| 用户1  | 5         | 1         | 动作片   |\n",
    "| 用户2  | 4         | 2         | 动作片   |\n",
    "| 用户3  | 2         | 5         | 喜剧片   |\n",
    "| 用户4  | 1         | 4         | 喜剧片   |\n",
    "| 用户5  | 3         | 2         | 动作片   |\n",
    "| 用户6  | 2         | 5         | 喜剧片   |\n",
    "\n",
    "你需要做以下步骤：\n",
    "1. 构造数据\n",
    "2. 创建KNN模型\n",
    "3. 使用数据训练模型\n",
    "4. 预测新用户的喜好"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 0. 引入核心包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.neighbors import KNeighborsClassifier"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. X, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = np.array([[5, 1], [4, 2], [2, 5], [1, 4], [3, 2], [2, 5]])\n",
    "\n",
    "y = np.array([0, 0, 1, 1,0,1])  # 0表示动作片，1表示喜剧片"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 创建 KNN 模型\n",
    "k = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "knn = KNeighborsClassifier(n_neighbors=1)  # k=1"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-2 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: black;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-2 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-2 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-2 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: block;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-2 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-2 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-2 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-2 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-2 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 1ex;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-2 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>KNeighborsClassifier(n_neighbors=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" checked><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;KNeighborsClassifier<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.neighbors.KNeighborsClassifier.html\">?<span>Documentation for KNeighborsClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>KNeighborsClassifier(n_neighbors=1)</pre></div> </div></div></div></div>"
      ],
      "text/plain": [
       "KNeighborsClassifier(n_neighbors=1)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn.fit(X, y)  # 训练模型"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. 用模型推理(预测)用户的喜好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_user = np.array([[3, 4]])\n",
    "prediction = knn.predict(new_user)  # 用模型推理(预测)用户的喜好"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. 数据可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.title(\"User Movie Preference\", size=15) \n",
    "plt.xlabel(\"Movie A rating\")\n",
    "plt.ylabel(\"Movie B rating\")\n",
    "plt.grid()\n",
    "\n",
    "# 绘制原始样本点，要求不同的影片喜好类别用不同的颜色标记\n",
    "# 提示: 用scatter散点图绘制，用它的参数c实现不同的类别用不同的颜色标记\n",
    "#TODO\n",
    "plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis')\n",
    "# 绘制新数据点，用红色x标记，大小为8\n",
    "# 提示：用plt.plot()绘制，用它的参数marker实现不同的标记符号\n",
    "#TODO\n",
    "plt.plot(new_user[0, 0], new_user[0, 1], 'rx', markersize=8)\n",
    "# 新数据最近邻索引为第一个最近邻的索引\n",
    "dist, idx = knn.kneighbors(new_user)\n",
    "nearest = X[idx[0]]#TODO # 获取最近邻点的坐标，这是一个列表，第一个元素是x坐标，第二个元素是y坐标\n",
    "\n",
    "# 用红线标记新数据点与最近邻点的连接线\n",
    "# 提示：用plt.plot()绘制，用 r-- 实现红色虚线\n",
    "#TODO\n",
    "plt.plot([new_user[0, 0], nearest[0, 0]], [new_user[0, 1], nearest[0, 1]], 'r--')\n",
    "# 为每个点添加坐标文本  \n",
    "for x, y in zip(X[:, 0], X[:, 1]):\n",
    "    plt.text(x, y+0.1, f'({x}, {y})') \n",
    "\n",
    "# 为新数据点添加坐标文本\n",
    "plt.text(new_user[0,0], new_user[0,1]+0.1, f'({new_user[0,0]}, {new_user[0,1]})')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
